package models

import (
	"time"
	"github.com/astaxie/beego/orm"
	"fmt"
	"strconv"
	"read.com/admin/libs"
	"encoding/base64"
	"strings"
)

type PayConfirm struct {
	OrderId       string    `orm:"column(order_id)" description:"订单号"`
	UserId        string    `orm:"column(user_id);size(8)" description:"用户ID"`
	AppId         int       `orm:"column(app_id)" description:"应用ID"`
	ItemId        int       `orm:"column(item_id);auto" description:"支付项ID"`
	ApplyDate     time.Time `orm:"column(apply_date);type(datetime)" description:"订单创建时间"`
	CommitDate    time.Time `orm:"column(commit_date);type(datetime)" description:"订单完成时间"`
	ConfirmDate   time.Time `orm:"column(confirm_date);type(datetime)" description:"订单接收时间"`
	Status        int8      `orm:"column(status)" description:"订单状态"`
	Amount        int       `orm:"column(amount)" description:"单价(分)"`
	PayType       int8      `orm:"column(pay_type)" description:"支付类型"`
	TransactionId string    `orm:"column(transaction_id);size(64)" description:"支付机构订单号"`
}

type OrderList struct {
	Nickname string
	AppName  string
	Type     int8
	Name     string
	Desc     string
	Price    int
	PayConfirm
}

func (t *PayConfirm) TableName() string {
	return "pay_confirm"
}

func init() {
	orm.RegisterModel(new(PayConfirm))
}

func GetAllCount() int {
	o := orm.NewOrm()
	count := 0
	o.Raw("select count(*) from pay_confirm where status = 1").QueryRow(&count)
	return count
}

func GetVipCount() int {
	o := orm.NewOrm()
	count := 0
	o.Raw("select count(*) from pay_confirm pc,pay_item pi where pc.item_id = pi.id and pi.type = 1").QueryRow(&count)
	return count
}

func GetDayProfit() float32 {
	o := orm.NewOrm()
	//("2006-01-02 15:04:05")
	start := time.Now().Format("2006-01-02 00:00:00")
	end := time.Now().Add(24 * time.Hour).Format("2006-01-02 00:00:00")
	amount := 0
	o.Raw("select sum(amount) from pay_confirm where commit_date >= ? and commit_date < ?", start, end).QueryRow(&amount)
	return float32(amount) / float32(100)
}

func GetWeekProfit() float32 {
	offset := 0
	var days = [...]string{
		"Sunday",
		"Monday",
		"Tuesday",
		"Wednesday",
		"Thursday",
		"Friday",
		"Saturday",
	}

	for k, v := range days {
		if v == time.Now().Weekday().String() {
			offset = k
		}
	}
	o := orm.NewOrm()
	start := time.Now().Add(time.Duration((1-offset)*24) * time.Hour).Format("2006-01-02 00:00:00")
	end := time.Now().Add(time.Duration((8-offset)*24) * time.Hour).Format("2006-01-02 00:00:00")
	amount := 0
	o.Raw("select sum(amount) from pay_confirm where commit_date >= ? and commit_date < ?", start, end).QueryRow(&amount)
	return float32(amount) / float32(100)
}

func GetMonthProfit() float32 {
	o := orm.NewOrm()
	year, month, _ := time.Now().Date()
	thisMonth := time.Date(year, month, 1, 0, 0, 0, 0, time.Local)
	start := thisMonth.AddDate(0, 0, 0).Format("2006-01-02 00:00:00")
	end := thisMonth.AddDate(0, 1, 0).Format("2006-01-02 00:00:00")
	amount := 0
	o.Raw("select sum(amount) from pay_confirm where commit_date >= ? and commit_date < ?", start, end).QueryRow(&amount)
	return float32(amount) / float32(100)
}

func GetTotalProfit() float32 {
	o := orm.NewOrm()
	amount := 0
	o.Raw("select sum(amount) from pay_confirm").QueryRow(&amount)
	return float32(amount) / float32(100)
}

func GetOrderList(page int, pageSize int, start string, end string, appId int) ([]map[string]string, int64, map[int]map[string]string) {
	o := orm.NewOrm()
	offset := (page - 1) * pageSize
	orderLists := make([]*OrderList, 0)
	count := 0
	con := ""
	if appId != -1 {
		con = "and pc.app_id = " + strconv.Itoa(appId)
	}
	if start == "" && end == "" {
		sqlStr := "select pc.*,pi.name,pi.desc,pi.price,pi.type,u.nickname " +
			"from pay_confirm pc,pay_item pi,user u " +
			"where pc.item_id = pi.id and pc.user_id = u.user_id " + con +
			" order by pc.commit_date desc limit " + strconv.Itoa(offset) + "," + strconv.Itoa(pageSize)
		o.Raw(sqlStr).QueryRows(&orderLists)
		sqlCount := "select count(*) from pay_confirm pc,pay_item pi,user u where pc.item_id = pi.id and pc.user_id = u.user_id " + con
		o.Raw(sqlCount).QueryRow(&count)
	} else {
		sqlStr := "select pc.*,pi.name,pi.desc,pi.price,pi.type,u.nickname " +
			"from pay_confirm pc,pay_item pi,user u " +
			"where pc.item_id = pi.id and pc.user_id = u.user_id and pc.commit_date between ? and ? " + con +
			" order by pc.commit_date desc limit " + strconv.Itoa(offset) + "," + strconv.Itoa(pageSize)
		o.Raw(sqlStr, libs.StrToTime(start), libs.StrToTime(end)).QueryRows(&orderLists)
		sqlCount := "select count(*) from pay_confirm pc,pay_item pi,user u where pc.item_id = pi.id and pc.user_id = u.user_id and pc.commit_date between ? and ? " + con
		o.Raw(sqlCount, libs.StrToTime(start), libs.StrToTime(end)).QueryRow(&count)
	}
	results := make([]map[string]string, 0)
	for i, v := range orderLists {
		if app, find := appHash[v.AppId]; find {
			v.AppName = app.AppName
		}
		nickName, _ := base64.StdEncoding.DecodeString(v.Nickname)
		result := map[string]string{
			"Sort":          strconv.Itoa(i + 1),
			"Nickname":      string(nickName),
			"AppName":       v.AppName,
			"Type":          strconv.Itoa(int(v.Type)),
			"Name":          v.Name,
			"Desc":          v.Desc,
			"Price":         strconv.Itoa(v.Price),
			"OrderId":       v.OrderId,
			"UserId":        v.UserId,
			"AppId":         strconv.Itoa(v.AppId),
			"ItemId":        strconv.Itoa(v.ItemId),
			"ApplyDate":     v.ApplyDate.Format("2006-01-02 15:04:05"),
			"CommitDate":    v.CommitDate.Format("2006-01-02 15:04:05"),
			"ConfirmDate":   v.ConfirmDate.Format("2006-01-02 15:04:05"),
			"Status":        strconv.Itoa(int(v.Status)),
			"Amount":        strconv.Itoa(v.Amount),
			"PayType":       strconv.Itoa(int(v.PayType)),
			"TransactionId": v.TransactionId,
		}
		results = append(results, result)
	}
	tableHead := map[int]map[string]string{
		0:{"sort":          "序号"},
		1:{"UserId":        "用户Id"},
		2:{"Nickname":      "用户名"},
		3:{"AppName":       "用户来源"},
		4:{"Type":          "订单类型"},
		5:{"Name":          "商品名称"},
		6:{"Desc":          "商品描述"},
		7:{"Price":         "商品价格"},
		8:{"PayType":       "支付方式"},
		9:{"Status":        "订单状态"},
		10:{"ApplyDate":     "订单产生时间"},
		11:{"CommitDate":    "订单支付时间"},
		12:{"OrderId":       "订单编号"},
		13:{"TransactionId": "第三方编码"},
	}
	return results, int64(count), tableHead
}

func GetCountAndSum(startTime, endTime string) (map[string]interface{}, error) {
	o := orm.NewOrm()
	start := libs.StrToTime(startTime + " 00:00:00")
	end := libs.StrToTime(endTime + " 00:00:00")
	if startTime == "" && endTime == "" {
		end = libs.StrToTime(time.Now().Format("2006-01-02 00:00:00"))
		start = end.AddDate(0, -1, 0)
	}
	days := int((end.Unix() - start.Unix()) / 24 / 3600)
	dates := make([]string, 0)
	counts := make([]int, 0)
	vipCounts := make([]int, 0)
	commonCounts := make([]int, 0)
	sums := make([]float32, 0)
	vipSums := make([]float32, 0)
	commonSums := make([]float32, 0)
	for i := 0; i < days+1; i++ {
		count := 0
		commonCount := 0
		sum := 0
		commonSum := 0
		commitDateStart := start.AddDate(0, 0, i)
		commitDateEnd := start.AddDate(0, 0, i+1)
		sqlStr := "select count(*) from pay_confirm where status = 1 and commit_date >= ? and commit_date < ?"
		err := o.Raw(sqlStr, commitDateStart, commitDateEnd).QueryRow(&count)
		sqlStr = "select count(*) from pay_confirm pc,pay_item pi where pc.item_id = pi.id and pi.type = 1 and pc.status = 1 and pc.commit_date >= ? and pc.commit_date < ?"
		err = o.Raw(sqlStr, commitDateStart, commitDateEnd).QueryRow(&commonCount)
		if err != nil {
			fmt.Println("select count pay_confirm error", err)
			return nil, err
		}
		counts = append(counts, count)
		commonCounts = append(commonCounts, commonCount)
		vipCounts = append(vipCounts, count-commonCount)
		dates = append(dates, libs.Substr(strings.Split(commitDateStart.Format("2006-01-02 15:04:05"), " ")[0],5,5))
		sqlStr = "select sum(amount) from pay_confirm where status = 1 and commit_date >= ? and commit_date < ?"
		err = o.Raw(sqlStr, commitDateStart, commitDateEnd).QueryRow(&sum)
		sqlStr = "select sum(pc.amount) from pay_confirm pc,pay_item pi where pc.item_id = pi.id and pi.type = 1 and pc.status = 1 and pc.commit_date >= ? and pc.commit_date < ?"
		err = o.Raw(sqlStr, commitDateStart, commitDateEnd).QueryRow(&commonSum)
		if err != nil {
			fmt.Println("select sum(amount) pay_confirm error", err)
			return nil, err
		}
		f := float32(sum)/100
		sums = append(sums, f)
		f = float32(commonSum)/100
		commonSums = append(commonSums, f)
		f = float32(sum-commonSum)/100
		vipSums = append(vipSums, f)
	}
	result := map[string]interface{}{
		"dates":        dates,
		"counts":       counts,
		"commonCounts": commonCounts,
		"vipCounts":    vipCounts,
		"sums":         sums,
		"commonSums":   commonSums,
		"vipSums":      vipSums,
	}
	return result, nil
}
